Honor cancellation tokens linked by custom test executors - #6565
Conversation
Resolve the test body token when a custom executor invokes the action so tokens linked by that executor reach injected CancellationToken parameters.
Greptile SummaryThe PR changes custom test-executor invocation to resolve the test-body cancellation token when the executor invokes its action, allowing tokens linked by that executor to reach injected
Confidence Score: 5/5The PR appears safe to merge, with the cancellation-token propagation change covered by reflection and source-generated execution tests. The custom-executor path now reads the execution context’s current linked token at action invocation, while the context token retains the original engine cancellation source and the regression test verifies the intended observable behavior.
|
| Filename | Overview |
|---|---|
| src/TUnit.Engine/TestExecutor.cs | Defers cancellation-token resolution until the custom executor invokes the test action, preserving engine cancellation while incorporating newly linked tokens. |
| tests/TUnit.Engine.Tests/TestExecutorCancellationTokenTests.cs | Adds filtered engine-level coverage that requires exactly one cancellation regression test to execute and pass across configured execution modes. |
| tests/TUnit.TestProject/TestExecutorCancellationTokenTests.cs | Adds a custom executor that links and cancels a token before invocation and verifies that the injected test-body token observes cancellation. |
Sequence Diagram
sequenceDiagram
participant Engine as TUnit Engine
participant Executor as Custom ITestExecutor
participant Context as TestContext.Execution
participant Test as Test Method
Engine->>Executor: ExecuteTest(context, action)
Executor->>Context: AddLinkedCancellationToken(token)
Executor->>Executor: Cancel linked token
Executor->>Engine: Invoke action
Engine->>Context: Read current CancellationToken
Engine->>Test: InvokeTestAsync(current token)
Test-->>Engine: Observes cancellation
Reviews (1): Last reviewed commit: "fix(engine): honor executor-linked cance..." | Re-trigger Greptile
Code reviewReviewed Summary: Verification:
Non-blocking observation: No blocking issues found. The change is minimal, well-targeted, and the root-cause explanation in the PR description matches what's in the code. |
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.63.0 to 1.64.6. <details> <summary>Release notes</summary> _Sourced from [TUnit's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.64.6 <!-- Release notes generated using configuration in .github/release.yml at v1.64.6 --> ## What's Changed ### Other Changes * Switch NuGet publishing to trusted publishing by @thomhurst in thomhurst/TUnit#6573 * Expose results directory through TestContext by @thomhurst in thomhurst/TUnit#6575 * Fix outcome timeline overflow in HTML reports by @thomhurst in thomhurst/TUnit#6574 ### Dependencies * chore(deps): update tunit to 1.64.0 by @thomhurst in thomhurst/TUnit#6570 **Full Changelog**: thomhurst/TUnit@v1.64.0...v1.64.6 ## 1.64.0 <!-- Release notes generated using configuration in .github/release.yml at v1.64.0 --> ## What's Changed ### Other Changes * Honor cancellation tokens linked by custom test executors by @thomhurst in thomhurst/TUnit#6565 * Fix linked cancellation from before-test hooks by @thomhurst in thomhurst/TUnit#6568 * Add per-test execution cancellation by @thomhurst in thomhurst/TUnit#6569 ### Dependencies * chore(deps): update tunit to 1.63.25 by @thomhurst in thomhurst/TUnit#6559 * chore(deps): update dependency serialize-javascript to v7.1.0 by @thomhurst in thomhurst/TUnit#6561 * chore(deps): update dependency nsubstitute to 6.1.0 by @thomhurst in thomhurst/TUnit#6564 * chore(deps): bump mermaid from 11.15.0 to 11.16.1 in /docs by @dependabot[bot] in thomhurst/TUnit#6563 * chore(deps): bump nanoid from 3.3.16 to 3.3.18 in /docs by @dependabot[bot] in thomhurst/TUnit#6562 **Full Changelog**: thomhurst/TUnit@v1.63.25...v1.64.0 ## 1.63.25 <!-- Release notes generated using configuration in .github/release.yml at v1.63.25 --> ## What's Changed ### Other Changes * Fix Mermaid label contrast in dark mode by @thomhurst in thomhurst/TUnit#6531 * Enhance matrix tests documentation by @koryphaee in thomhurst/TUnit#6537 * fix: support nested Member after IsTypeOf by @mvanhorn in thomhurst/TUnit#6540 * docs: Add documentation for TestContext.Parameters by @thomhurst with @Copilot in thomhurst/TUnit#6558 * fix: run event receivers on injected properties by @thomhurst in thomhurst/TUnit#6556 ### Dependencies * chore(deps): update tunit to 1.63.0 by @thomhurst in thomhurst/TUnit#6526 * chore(deps): update dependency stackexchange.redis to 3.1.0 by @thomhurst in thomhurst/TUnit#6529 * chore(deps): update verify to 31.28.0 by @thomhurst in thomhurst/TUnit#6532 * chore(deps): update dependency stackexchange.redis to 3.1.3 by @thomhurst in thomhurst/TUnit#6541 * chore(deps): update dependency dompurify to v3.4.13 by @thomhurst in thomhurst/TUnit#6542 * chore(deps): update dependency rabbitmq.client to 7.2.2 by @thomhurst in thomhurst/TUnit#6546 * chore(deps): update dependency polyfill to 11.0.2 by @thomhurst in thomhurst/TUnit#6549 * chore(deps): update dependency polyfill to 11.0.2 by @thomhurst in thomhurst/TUnit#6548 * chore(deps): bump fast-uri from 3.1.4 to 3.1.5 in /docs by @dependabot[bot] in thomhurst/TUnit#6545 * chore(deps): bump postcss from 8.5.22 to 8.5.25 in /docs by @dependabot[bot] in thomhurst/TUnit#6547 * chore(deps): update dependency stackexchange.redis to 3.1.11 by @thomhurst in thomhurst/TUnit#6550 * chore(deps): update dependency stackexchange.redis to 3.1.13 by @thomhurst in thomhurst/TUnit#6552 ## New Contributors * @koryphaee made their first contribution in thomhurst/TUnit#6537 **Full Changelog**: thomhurst/TUnit@v1.63.0...v1.63.25 Commits viewable in [compare view](thomhurst/TUnit@v1.63.0...v1.64.6). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.63.0 to 1.64.6. <details> <summary>Release notes</summary> _Sourced from [TUnit.Core's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.64.6 <!-- Release notes generated using configuration in .github/release.yml at v1.64.6 --> ## What's Changed ### Other Changes * Switch NuGet publishing to trusted publishing by @thomhurst in thomhurst/TUnit#6573 * Expose results directory through TestContext by @thomhurst in thomhurst/TUnit#6575 * Fix outcome timeline overflow in HTML reports by @thomhurst in thomhurst/TUnit#6574 ### Dependencies * chore(deps): update tunit to 1.64.0 by @thomhurst in thomhurst/TUnit#6570 **Full Changelog**: thomhurst/TUnit@v1.64.0...v1.64.6 ## 1.64.0 <!-- Release notes generated using configuration in .github/release.yml at v1.64.0 --> ## What's Changed ### Other Changes * Honor cancellation tokens linked by custom test executors by @thomhurst in thomhurst/TUnit#6565 * Fix linked cancellation from before-test hooks by @thomhurst in thomhurst/TUnit#6568 * Add per-test execution cancellation by @thomhurst in thomhurst/TUnit#6569 ### Dependencies * chore(deps): update tunit to 1.63.25 by @thomhurst in thomhurst/TUnit#6559 * chore(deps): update dependency serialize-javascript to v7.1.0 by @thomhurst in thomhurst/TUnit#6561 * chore(deps): update dependency nsubstitute to 6.1.0 by @thomhurst in thomhurst/TUnit#6564 * chore(deps): bump mermaid from 11.15.0 to 11.16.1 in /docs by @dependabot[bot] in thomhurst/TUnit#6563 * chore(deps): bump nanoid from 3.3.16 to 3.3.18 in /docs by @dependabot[bot] in thomhurst/TUnit#6562 **Full Changelog**: thomhurst/TUnit@v1.63.25...v1.64.0 ## 1.63.25 <!-- Release notes generated using configuration in .github/release.yml at v1.63.25 --> ## What's Changed ### Other Changes * Fix Mermaid label contrast in dark mode by @thomhurst in thomhurst/TUnit#6531 * Enhance matrix tests documentation by @koryphaee in thomhurst/TUnit#6537 * fix: support nested Member after IsTypeOf by @mvanhorn in thomhurst/TUnit#6540 * docs: Add documentation for TestContext.Parameters by @thomhurst with @Copilot in thomhurst/TUnit#6558 * fix: run event receivers on injected properties by @thomhurst in thomhurst/TUnit#6556 ### Dependencies * chore(deps): update tunit to 1.63.0 by @thomhurst in thomhurst/TUnit#6526 * chore(deps): update dependency stackexchange.redis to 3.1.0 by @thomhurst in thomhurst/TUnit#6529 * chore(deps): update verify to 31.28.0 by @thomhurst in thomhurst/TUnit#6532 * chore(deps): update dependency stackexchange.redis to 3.1.3 by @thomhurst in thomhurst/TUnit#6541 * chore(deps): update dependency dompurify to v3.4.13 by @thomhurst in thomhurst/TUnit#6542 * chore(deps): update dependency rabbitmq.client to 7.2.2 by @thomhurst in thomhurst/TUnit#6546 * chore(deps): update dependency polyfill to 11.0.2 by @thomhurst in thomhurst/TUnit#6549 * chore(deps): update dependency polyfill to 11.0.2 by @thomhurst in thomhurst/TUnit#6548 * chore(deps): bump fast-uri from 3.1.4 to 3.1.5 in /docs by @dependabot[bot] in thomhurst/TUnit#6545 * chore(deps): bump postcss from 8.5.22 to 8.5.25 in /docs by @dependabot[bot] in thomhurst/TUnit#6547 * chore(deps): update dependency stackexchange.redis to 3.1.11 by @thomhurst in thomhurst/TUnit#6550 * chore(deps): update dependency stackexchange.redis to 3.1.13 by @thomhurst in thomhurst/TUnit#6552 ## New Contributors * @koryphaee made their first contribution in thomhurst/TUnit#6537 **Full Changelog**: thomhurst/TUnit@v1.63.0...v1.63.25 Commits viewable in [compare view](thomhurst/TUnit@v1.63.0...v1.64.6). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Summary
ITestExecutorinvokes its actionRoot cause
The executor action captured the engine cancellation token before the custom executor ran. Calling
context.Execution.AddLinkedCancellationToken(...)updated the context, but the test method still received the stale captured token.User impact
Custom test executors can now link and cancel a token before invoking the test body, and an injected
CancellationTokenobserves that cancellation. This enables the background-failure executor pattern discussed in discussion #3099.Validation
dotnet build tests/TUnit.TestProject/TUnit.TestProject.csproj -c Release --no-restore --nologonet8.0,net9.0, andnet10.0net10.0AOT runtime coverage remains enabled for CI; it is skipped locally by the existing test harness.